﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace Baula.TextGen.ActiveTemplating.Tests
{
    [TestClass]
    public class EngineTestsWithMockedExecutor
    {
        private Engine _engine;
        private Context _context;
        private Mock<IFormsContext> _formsContext;
        private Mock<DefaultContext> _defaultContext;
        private Mock<TemplateToVBConverter> _converter;
        private Mock<IExecutor> _executor;

        [TestInitialize]
        public void TestInitialize()
        {
            _formsContext = new Mock<IFormsContext>();
            _defaultContext = new Mock<DefaultContext>();
            _converter = new Mock<TemplateToVBConverter>();
            _context = new Context(_defaultContext.Object, _formsContext.Object, null);
            _executor = new Mock<IExecutor>();
            _executor.SetupGet(e => e.Context).Returns(_context);
            var defaultContextMapping = new Mock<DefaultContextMapping>();
            defaultContextMapping.Setup(
                dcm => dcm.GetCodeForWellKnownPlaceholder(It.IsAny<string>())).Returns(string.Empty);

            _engine = new Engine(_converter.Object, _executor.Object, defaultContextMapping.Object);
        }

        [TestMethod]
        public void PassesTemplateToConverter()
        {
            const string template = "Some arbitrary template";
            _engine.Process(template);
            _converter.Verify(c => c.Convert(template));
        }

        [TestMethod]
        public void PassesConversionResultToExecutor()
        {
            const string convertedTemplate = "converted template";
            _converter.Setup(c => c.Convert(It.IsAny<string>())).Returns(convertedTemplate);
            _engine.Process("dummy");
            _executor.Verify(e => e.Execute(convertedTemplate));
        }

        [TestMethod]
        public void ReturnsExecutionResultToOutput()
        {
            const string executionResult = "The result";
            _executor.SetupGet(e => e.Output).Returns(executionResult);
            var actual = _engine.Process("dummy");
            Assert.AreEqual(executionResult, actual);
        }
    }

    [TestClass]
    public class EngineTestsWithRealExecution
    {
        private Engine _engine;
        private Mock<IFormsContext> _formsContext;
        private Mock<DefaultContext> _defaultContext;

        [TestInitialize]
        public void TestInitialize()
        {
            _defaultContext = new Mock<DefaultContext>();
            _formsContext = new Mock<IFormsContext>();
            var context = new Context(_defaultContext.Object, _formsContext.Object, null);

            var defaultContextMapping = new Mock<DefaultContextMapping>();
            defaultContextMapping.Setup(dcm => dcm.WellKnownPlaceholders)
                .Returns(new[] { "MODULE_NAME", "PROCEDURE_NAME" });
            defaultContextMapping.Setup(
                dcm => dcm.GetCodeForWellKnownPlaceholder("PROCEDURE_NAME")).Returns("Context.DefaultContext.ProcedureName");
            defaultContextMapping.Setup(
                dcm => dcm.GetCodeForWellKnownPlaceholder("MODULE_NAME")).Returns("Context.DefaultContext.ModuleName");

            _engine = new Engine(new TemplateToVBConverter(), new Executor(context), defaultContextMapping.Object);
        }

        //[TestMethod]
        public void FormsCount_IsTakenFromFormsContext()
        {
            _engine.Process("{Forms.Count}");
            _formsContext.VerifyGet(fc => fc.Count, Times.Once());
        }

        [TestMethod]
        public void ModuleName_IsTakenFromDefaultContext()
        {
            _engine.Process("{MODULE_NAME}");
            _defaultContext.VerifyGet(dc => dc.ModuleName, Times.Once());
        }

        [TestMethod]
        public void ProcedureName_IsTakenFromDefaultContext()
        {
            _engine.Process("{PROCEDURE_NAME}");
            _defaultContext.VerifyGet(dc => dc.ProcedureName, Times.Once());
        }
    }
}